CashWheelClient.tsx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. "use client";
  2. import { getWheelApi, getWheelReceiveApi, WheelsType } from "@/api/cashWheel";
  3. import Box from "@/components/Box";
  4. import { WheelClient } from "@/components/Box/WheelModal";
  5. import { Link } from "@/i18n/routing";
  6. import { useUserInfoStore } from "@/stores/useUserInfoStore";
  7. import { server } from "@/utils/client";
  8. import { copyText, timeFormat } from "@/utils/methods";
  9. import { useCountDown } from "ahooks";
  10. import { Popup, Toast } from "antd-mobile";
  11. import clsx from "clsx";
  12. import { useTranslations } from "next-intl";
  13. import Image from "next/image";
  14. import { createContext, FC, Fragment, useContext, useEffect, useState } from "react";
  15. import LotteryWheel from "./LotteryWheel";
  16. import styles from "./style.module.scss";
  17. interface Props {
  18. // wheel: WheelsType;
  19. allHistory: any[];
  20. phones: any[];
  21. }
  22. interface ContextType extends WheelsType, Props {
  23. handler: () => void;
  24. }
  25. const WheelContext = createContext<Partial<ContextType>>({});
  26. const CashMainCom = () => {
  27. return (
  28. <div className={`${styles.cashMain} ${styles.cashMain} ${styles.type1}`}>
  29. <div className={styles.haveCash}>
  30. <img src="/wheel/cash.png" alt="" className={styles.cashImg} />
  31. <div>
  32. {" "}
  33. R$ <span className={styles.cash}>94.15</span>
  34. </div>
  35. <span className={styles.withdraw}>
  36. <img src="/wheel/pix.png" alt="" /> SACAR{" "}
  37. </span>
  38. </div>
  39. <div className={styles.progress}>
  40. <div className={styles.num}> 94.15%</div>
  41. <div className={styles.bar}>
  42. <span style={{ width: "calc(97.15% - 0.07rem)" }}></span>
  43. </div>
  44. </div>
  45. <div className={styles.needCash}>
  46. {" "}
  47. Ainda e necessário <span className={styles.needCashNum}>5.85</span> para realizar do
  48. saque{" "}
  49. </div>
  50. </div>
  51. );
  52. };
  53. const DrawMain1 = () => {
  54. return (
  55. <div className={styles.drawMain}>
  56. <div className={styles.draw}>
  57. {/*<img src="/wheel/d.png" className={styles.lamp} />*/}
  58. {/*<img src="/wheel/light1.png" className={styles.light1} />*/}
  59. {/*<img src="/wheel/light2.png" className={styles.light2} />*/}
  60. {/*<div className={styles.pointer}>*/}
  61. {/* <img src="/wheel/pointer.png" />*/}
  62. {/*</div>*/}
  63. {/*<img src="/wheel/bg_light.png" className={styles.drawBgImg} />*/}
  64. {/*<div className={`${styles.drawLen} ${styles.position} `}></div>*/}
  65. {/* <div className={styles.drawContents}>
  66. <canvas id={styles.draw} width={306} height={306} />
  67. </div> */}
  68. <LotteryWheel />
  69. </div>
  70. </div>
  71. );
  72. };
  73. const DrawContent = () => {
  74. return (
  75. <div className={styles.drawContent}>
  76. <div className={styles.text}>
  77. <span>
  78. <span style={{ color: "rgb(135, 149, 177)" }}>Expira em</span> 2d 19:18:13
  79. </span>
  80. </div>
  81. <div className={styles.cashButton}>
  82. <div> Convide amigos para ajudar com saques</div>
  83. <div className={`${styles.iconfont} ${styles.iconShare}`}></div>
  84. </div>
  85. </div>
  86. );
  87. };
  88. type Dtltype = "left" | "right";
  89. const LeftListClient = () => {
  90. const wheel = useContext(WheelContext);
  91. return (
  92. <>
  93. <div className={`${styles.winList} ${styles.swipernoswiping} ${styles.type2}`}>
  94. {wheel.allHistory &&
  95. wheel.allHistory.length > 0 &&
  96. wheel.allHistory?.map((item, index) => {
  97. return (
  98. <div className={styles.item} key={index}>
  99. <span className={`${styles.name} ${styles.omitWrap}`}>
  100. {item.phone_number}
  101. </span>
  102. <span className={styles.tipText}>
  103. {timeFormat(item.receive_time, "br", undefined, true)}
  104. </span>
  105. <div className={styles.value}>
  106. <span className={styles.addCash}>+100</span>
  107. <span className={styles.unit}> R$</span>
  108. </div>
  109. </div>
  110. );
  111. })}
  112. </div>
  113. </>
  114. );
  115. };
  116. const getSelfHistoryApi = () => {
  117. return server.request<any[]>({
  118. url: "/v1/api/user/turntable/self_receive",
  119. method: "POST",
  120. });
  121. };
  122. const RightListClient = () => {
  123. const [selfHistory, setSelfHistory] = useState<any[]>([]);
  124. useEffect(() => {
  125. getSelfHistoryApi().then((res) => {
  126. setSelfHistory(res.data);
  127. });
  128. }, []);
  129. return (
  130. <div className={"h-[100%] overflow-scroll p-[10px]"}>
  131. <div
  132. className={
  133. "grid grid-cols-[1.3889rem_1fr_0.6944rem] gap-y-[0.1389rem] text-[0.0972rem]" +
  134. " text-[#8795b1]"
  135. }
  136. >
  137. {selfHistory.map((item, index) => {
  138. return (
  139. <Fragment key={index}>
  140. <div className={"flex"}>
  141. <span className={"mr-[0.0694rem] text-[0.12rem] text-[#6ddf39]"}>
  142. +{item.lose_amount}
  143. </span>
  144. <div
  145. className={
  146. "h-[0.16rem] w-[0.16rem] rounded-[50%] bg-[#6ddf39] text-center" +
  147. " text-[0.07rem] leading-[0.16rem] text-[#fff]"
  148. }
  149. >
  150. R$
  151. </div>
  152. </div>
  153. <div className={"flex flex-1"}>
  154. {" "}
  155. {timeFormat(item.receive_time, "br", undefined)}
  156. </div>
  157. <div className={"flex items-center justify-end text-[#f0ae18]"}>
  158. <Image
  159. className={"mr-[0.0694rem] object-contain"}
  160. src={"/wheels/group.png"}
  161. alt={"group"}
  162. width={20}
  163. height={8}
  164. />
  165. <span>+{item.count_person}</span>
  166. </div>
  167. </Fragment>
  168. );
  169. })}
  170. </div>
  171. </div>
  172. );
  173. };
  174. const Report = () => {
  175. const [activeTab, setActiveTab] = useState<Dtltype>("left");
  176. const handler = (dtl: Dtltype) => {
  177. setActiveTab(dtl);
  178. };
  179. const activeClass = clsx(
  180. styles.vanTabItem,
  181. activeTab === "left" ? styles.vanTabAcriveLeft : styles.vanTabAcriveRight
  182. );
  183. return (
  184. <div className={styles.report}>
  185. <div className={`${styles.vanTabs} ${styles.vanTabsLine}`}>
  186. <div className={styles.vanTabsWrap}>
  187. <div className={styles.vanTabsNav}>
  188. <div
  189. className={`${styles.vanTabItem} ${activeTab === "right" ? styles.vanTabAcriveRight : ""} `}
  190. onClick={() => handler("left")}
  191. >
  192. <span className={activeTab === "left" ? styles.activeText : ""}>
  193. Relatório
  194. </span>
  195. </div>
  196. <div
  197. className={`${styles.vanTabItem} ${activeTab === "left" ? styles.vanTabAcriveLeft : ""}`}
  198. onClick={() => handler("right")}
  199. >
  200. <span className={activeTab === "right" ? styles.activeText : ""}>
  201. Minha Referencia
  202. </span>
  203. </div>
  204. </div>
  205. </div>
  206. <div className={styles.vanTabsContent}>
  207. <div className={styles.vantabpane}>
  208. <div className={styles.tabContent}>
  209. {activeTab === "left" ? <LeftListClient /> : <RightListClient />}
  210. </div>
  211. </div>
  212. </div>
  213. </div>
  214. <div className={styles.rules}>
  215. <h2>Regras</h2>
  216. <ul className={styles.tipsContent}>
  217. <li>1.Você pode iniciar um saque quando o valor acumulado atingir 100 BRL. </li>
  218. <li>
  219. 2.Convidar amigos para se registrarem no 9f.com irá ajudá- lo a sacar
  220. dinheiro rapidamente.
  221. </li>
  222. <li>3. Cada usuário receberá uma única rodada grátis por dia. </li>
  223. <li>
  224. 4.Cada usuário tem um período de validade de 3 dias para cada atividade e
  225. pode participar da atividade várias vezes.
  226. </li>
  227. <li>
  228. 5.Se você receber um bônus de dinheiro extra, pode jogar jogos de graça e
  229. ganhar ainda mais dinheiro real.
  230. </li>
  231. <li>6.Se voce nao retirar o dinheiro dentro de 3 dias,ele ser perdido.</li>
  232. </ul>
  233. </div>
  234. </div>
  235. );
  236. };
  237. const WheelWallet = () => {
  238. const user = useUserInfoStore((state) => state.userInfo);
  239. const wheel = useContext(WheelContext);
  240. return (
  241. <Box className={"w-[100%]"}>
  242. <div
  243. className={
  244. "relative h-[1.6389rem] w-[100%] " +
  245. " flex flex-col bg-[url(/wheels/wheel-wallet.png)]" +
  246. " bg-[length:100%_100%]"
  247. }
  248. >
  249. <div className={"flex-1 p-[0.1389rem]"}>
  250. <div className={"text-[#49c25a]"}>
  251. <span className={"iconfont icon-yonghu"}></span>
  252. <span>Conta</span>
  253. <span>{user.user_phone}</span>
  254. </div>
  255. <div className={"text-[0.4861rem] font-bold text-[#008213]"}>
  256. R$ <span>{wheel.activate?.amount || 0}</span>
  257. </div>
  258. </div>
  259. <div
  260. className={
  261. "flex h-[0.4167rem] w-[100%] items-center justify-center text-center text-[0.125rem] font-bold"
  262. }
  263. >
  264. <span className={"mr-[10px] text-[#008213]"}>Faltam para O saque</span>
  265. <span className={"text-[#eef100]"}>
  266. R${(wheel.num! - wheel.activate?.amount! || 0).toFixed(2)}
  267. </span>
  268. </div>
  269. {/*top*/}
  270. </div>
  271. </Box>
  272. );
  273. };
  274. const DrawMain = () => {
  275. const wheel = useContext(WheelContext);
  276. return (
  277. <div className={"relative"}>
  278. <WheelWallet />
  279. <div className={"-mt-[0.2083rem] transform"}>
  280. <WheelClient isRotate={true} wheel={wheel} onRotateEnd={wheel.handler!} />
  281. </div>
  282. </div>
  283. );
  284. };
  285. const CountdownClient = () => {
  286. const wheel = useContext(WheelContext);
  287. const [_, formattedRes] = useCountDown({
  288. leftTime: wheel.activate?.end_time! * 1000 - Date.now(),
  289. });
  290. const { days, hours, minutes, seconds } = formattedRes;
  291. const receiveHandler = () => {
  292. getWheelReceiveApi({ unique_id: wheel.not_receive![0].unique_id }).then((res) => {
  293. wheel.handler && wheel.handler();
  294. });
  295. };
  296. return (
  297. <div className={"relative flex justify-center"}>
  298. {wheel.not_receive && wheel.not_receive.length > 0 ? (
  299. <div className={"mt-[10px]"}>
  300. <Image
  301. src={"/wheels/receive-button.png"}
  302. alt={"receive"}
  303. height={80}
  304. width={160}
  305. onClick={receiveHandler}
  306. ></Image>
  307. </div>
  308. ) : (
  309. <>
  310. <img src="/wheels/countdown-bg.png" alt="" />
  311. <span className={"absolute bottom-[50%] ml-[0.2083rem] translate-y-1/2"}>
  312. {String(days).padStart(2, "0")}:{String(hours).padStart(2, "0")}:
  313. {String(minutes).padStart(2, "0")}:{String(seconds).padStart(2, "0")}
  314. </span>
  315. </>
  316. )}
  317. </div>
  318. );
  319. };
  320. const phones = Array(9)
  321. .fill(0)
  322. .map((_, i) => {
  323. const num = `557894567${Math.floor(Math.random() * 1000)
  324. .toString()
  325. .padStart(4, "0")}`;
  326. return num;
  327. });
  328. const ShareClient = () => {
  329. const [visible, setVisible] = useState(false);
  330. const wheel = useContext(WheelContext);
  331. const user = useUserInfoStore((state) => state.userInfo);
  332. const [currentPhoneIndex, setCurrentPhoneIndex] = useState(0);
  333. const shareUrl = `${process.env.NEXT_PUBLIC_SHARE_URL}/br/sharecwbr?turntable=${wheel.activities && wheel.activities[0].id}&user=${user.id}&time=${wheel.activate?.end_time}`;
  334. const url = encodeURIComponent(`${shareUrl}`);
  335. const text = encodeURIComponent(`Receba 100 BRL de graça,Pix SAQUE RÁPIDO`);
  336. const t = useTranslations();
  337. const SHARE_SOURCE = [
  338. {
  339. icon: "/summary/Facebook.png",
  340. label: "Facebook",
  341. shareUrl: `https://www.facebook.com/sharer/sharer.php?u=${url}&t=${text}`,
  342. },
  343. {
  344. icon: "/summary/WhatsApp.png",
  345. label: "WhatsApp",
  346. shareUrl: `https://api.whatsapp.com/send?text=${text}`,
  347. },
  348. {
  349. icon: "/summary/Telegram.png",
  350. label: "Telegram",
  351. shareUrl: `https://t.me/share/url?url=${url}&text=${text}`,
  352. },
  353. {
  354. icon: "/summary/Twitter.png",
  355. label: "Twitter",
  356. shareUrl: `https://twitter.com/intent/tweet?text=${text}`,
  357. },
  358. {
  359. icon: "/summary/Email.png",
  360. label: "Email",
  361. shareUrl: `mailto: ?&subject=&cc=&bcc=&body=${url}%0A${text}`,
  362. },
  363. ];
  364. const copy = (text: string) => {
  365. copyText(text);
  366. Toast.show({ icon: "success", content: t("SummaryPage.copySuc"), maskClickable: false });
  367. };
  368. const handler = () => {
  369. const current = wheel.phones?.[currentPhoneIndex];
  370. window.open(`https://wa.me/${current}`);
  371. setCurrentPhoneIndex((value) => (value += 1));
  372. };
  373. return (
  374. <>
  375. <div className={"p-[0.1389rem]"}>
  376. <div
  377. className={
  378. "rounded-[0.1111rem] bg-gradient-to-b from-[#84ea24_20%] to-[#1b781a]" +
  379. " h-[0.4861rem]"
  380. }
  381. >
  382. <div className={"flex h-[100%] p-[0.0694rem]"}>
  383. <div
  384. className={
  385. "flex-1 rounded-[0.0694rem] bg-[rgba(255,255,255,0.5)]" +
  386. " flex items-center pl-[0.0694rem]"
  387. }
  388. >
  389. <span className={""}>Compartilhe mais, saque mais rápido.</span>
  390. </div>
  391. <div
  392. className={"flex w-[0.4167rem] items-center pl-[0.0694rem]"}
  393. onClick={() => setVisible(true)}
  394. >
  395. <Image src={"/wheels/share.png"} alt={"share"} width={30} height={30} />
  396. </div>
  397. </div>
  398. </div>
  399. </div>
  400. <Popup
  401. visible={visible}
  402. getContainer={null}
  403. onMaskClick={() => {
  404. setVisible(false);
  405. }}
  406. onClose={() => {
  407. setVisible(false);
  408. }}
  409. showCloseButton
  410. bodyStyle={{ background: "#fff" }}
  411. >
  412. <div className={"p-[0.1389rem] text-[#555555]"}>
  413. <h1>1.Convide amlgos para ajudar com saques</h1>
  414. <div
  415. className={"mt-[0.1389rem] grid grid-cols-5 justify-center gap-[0.1389rem]"}
  416. >
  417. {SHARE_SOURCE.map((source, index) => {
  418. return (
  419. <a
  420. href={source.shareUrl}
  421. key={index}
  422. target={"_blank"}
  423. className={"flex flex-col items-center"}
  424. >
  425. <Image src={source.icon} alt={"Mais"} width={70} height={70} />
  426. <p className={"mt-[0.0347rem] text-[12px] text-[#808080]"}>
  427. {source.label}
  428. </p>
  429. </a>
  430. );
  431. })}
  432. </div>
  433. <div className={"mt-[0.0694rem]"}>
  434. <h1 className={"text-[14px]"}>
  435. Compartilhe este link de indicação com seus amigos
  436. </h1>
  437. <div
  438. className={
  439. "rounded-[3px] bg-[#f9f9f9] p-[0.0694rem] text-[#808080]" +
  440. " mt-[0.0347rem] flex items-center"
  441. }
  442. >
  443. <span className={"mr-[0.0694rem] flex-1 truncate"}>{shareUrl}</span>
  444. <span
  445. id="copy"
  446. className={"text-[#40a1de]"}
  447. onClick={() => copy(shareUrl)}
  448. >
  449. {t("SummaryPage.Cópia")}
  450. </span>
  451. </div>
  452. </div>
  453. <div className={"mt-[0.0694rem]"}>
  454. <h1>2.Enviar convite para jogador aleatório ajudar</h1>
  455. <div className={"mt-[0.0694rem] bg-[#000] p-[10px]"}>
  456. <div className={"grid grid-cols-3 gap-[5px] text-[0.0833rem]"}>
  457. {wheel.phones?.map((phone, index) => {
  458. return (
  459. <span
  460. style={{
  461. color: index < currentPhoneIndex ? "#fff" : "#ccc",
  462. }}
  463. key={index}
  464. >
  465. {phone}
  466. </span>
  467. );
  468. })}
  469. </div>
  470. <div
  471. className={
  472. "grid grid-cols-2 gap-[0.1389rem] text-[0.12rem] text-[#fff]"
  473. }
  474. >
  475. <div
  476. onClick={handler}
  477. className={
  478. "flex items-center rounded-[0.0694rem] bg-[#10cb8c]" +
  479. " p-[0.0694rem] text-[#fff]"
  480. }
  481. >
  482. <div className={"flex-1"}>
  483. <p>Enviar Mensagem </p>
  484. <p>no WhatsAPP</p>
  485. </div>
  486. <Image
  487. src={"/summary/WhatsApp-nobg.png"}
  488. alt={"whatsApp"}
  489. width={40}
  490. height={40}
  491. />
  492. </div>
  493. <Link
  494. href={`sms:${wheel.phones?.join(";")}?body=message_body`}
  495. className={
  496. "flex items-center rounded-[10px] bg-[#35b2fe]" +
  497. " p-[0.0694rem] text-[#fff]"
  498. }
  499. >
  500. <div className={"flex-1"}>
  501. <p>Enviar Mensagem </p>
  502. <p>SMS</p>
  503. </div>
  504. <Image
  505. src={"/summary/SMS.png"}
  506. alt={"whatsApp"}
  507. width={40}
  508. height={40}
  509. />
  510. </Link>
  511. </div>
  512. </div>
  513. </div>
  514. </div>
  515. </Popup>
  516. </>
  517. );
  518. };
  519. const CashWheelClient: FC<Props> = (props) => {
  520. const getWheelData = async () => {
  521. return getWheelApi().then((res) => {
  522. if (res.code === 200) {
  523. setValues((staticValue) => {
  524. return { ...staticValue, ...res.data };
  525. });
  526. }
  527. return res;
  528. });
  529. };
  530. const [values, setValues] = useState<Partial<ContextType>>({
  531. num: 100,
  532. allHistory: props.allHistory || [],
  533. phones: props.phones || [],
  534. handler: getWheelData,
  535. });
  536. useEffect(() => {
  537. getWheelData();
  538. }, []);
  539. return (
  540. <>
  541. <WheelContext.Provider value={values}>
  542. <DrawMain />
  543. {/*倒计时*/}
  544. <CountdownClient />
  545. {/*分享*/}
  546. {values.activate && values.activate?.end_time > 0 ? <ShareClient /> : null}
  547. <div className={styles.cashWheelClient}>
  548. {/*<CashMainCom />*/}
  549. {/*<DrawContent />*/}
  550. <Report />
  551. {/*<LotteryWheel />*/}
  552. </div>
  553. </WheelContext.Provider>
  554. </>
  555. );
  556. };
  557. export default CashWheelClient;